package com.lv.common.utils.download

/**
 * 作者： ygx
 * 创建日期：2023/2/11 2:44 PM
 * 签名： 天行健，君子以自强不息；地势坤，君子以厚德载物。
 * -    _              _           _     _   ____  _             _ _
 * -   / \   _ __   __| |_ __ ___ (_) __| | / ___|| |_ _   _  __| (_) ___
 * -  / _ \ | '_ \ / _` | '__/ _ \| |/ _` | \___ \| __| | | |/ _` | |/ _ \
 * - / ___ \| | | | (_| | | | (_) | | (_| |  ___) | |_| |_| | (_| | | (_) |
 * -/_/   \_\_| |_|\__,_|_|  \___/|_|\__,_| |____/ \__|\__,_|\__,_|_|\___/
 * <p>
 * You never know what you can do until you try !
 * ----------------------------------------------------------------
 * 描述：
 */

import com.blankj.utilcode.util.LogUtils
import com.lv.common.utils.YgxUtilsKt
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import okhttp3.*
import java.io.*
import java.net.UnknownHostException

object DownloadGO {
    /**
     * @param url 文件下载连接
     * @param targetParent 需要保存到指定文件夹目录（tips: 是文件夹）
     */
    fun download(url: String, targetParent: String): Flow<DownloadStatus> {

        var bufferedInputStream: BufferedInputStream? = null
        var outputStream: FileOutputStream? = null
        var inputStream: InputStream? = null

        return flow {

            //下载前先检查 是否已经存在本地了
            val localFile = checkDownloadFile(url, targetParent)
            if (localFile != null) {
                //这里表示本地已经存在了已经下载好的文件
                LogUtils.e("文件已经存在")
                emit(DownloadStatus.onSuccess(localFile))

            } else {
                //执行下载

                val request = Request.Builder().url(url).get().build()
                val response = OkHttpClient.Builder().build().newCall(request).execute()

                val code = response.code


                LogUtils.e("download: code :${code}")

                //网络有响应成功，且body 不为空
                LogUtils.e("download: response.isSuccessful :${response.isSuccessful}")

                if (response.isSuccessful  ) {

                    saveFile(url, targetParent, response).collect {
                        emit(it)
                    }

                } else {
                    //请求失败的情况
                    if (code == 404) {
                        emit(DownloadStatus.onUrlUnkownFail())
                    }
                    emit(DownloadStatus.onFail(null))
                }
            }

        }.catch { error ->
            //捕获到异常了
            LogUtils.e("catch:error:${error}")

            if (error is UnknownHostException) {
                //无网络
                emit(DownloadStatus.onNetFail())
            }
            emit(DownloadStatus.onFail(null))

        }.onCompletion {
            bufferedInputStream?.close()
            outputStream?.close()
            inputStream?.close()
        }.flowOn(Dispatchers.IO)
    }

    fun saveFile(
        url: String,
        targetParent: String,
        response: Response,
    ): Flow<DownloadStatus> {

        var bufferedInputStream: BufferedInputStream? = null
        var outputStream: FileOutputStream? = null
        var inputStream: InputStream? = null

        LogUtils.e("1-2")

        return flow {


            val body = response.body
            val contentLength:Long = body!!.contentLength()
            inputStream = body!!.byteStream()

            LogUtils.e("contentLength:${contentLength}")

            //使用临时文件保存
            val tmpFile = getFileTmpName(url)
            val file = File(targetParent, tmpFile)

            outputStream = FileOutputStream(file)

            val bufferSize = 1024 * 8
            val buffer = ByteArray(bufferSize)


            bufferedInputStream = BufferedInputStream(inputStream, bufferSize)

            var readLength: Int
            var currentLength = 0L

            var oldProgress = 0L
            while (bufferedInputStream!!.read(buffer, 0, bufferSize)
                    .also { readLength = it } != -1
            ) {

                outputStream!!.write(buffer, 0, readLength)
                currentLength += readLength

                val currentProgress = currentLength * 100 / contentLength
//                LogUtils.e("currentProgress:${currentProgress} \n currentLength:${currentLength}")
                if (currentProgress - oldProgress >= 1) {
                    oldProgress = currentProgress
                    emit(DownloadStatus.onProgress(currentProgress))
                }

            }


            emit(DownloadStatus.onProgress(100L))

            //修改文件名字
            val newFile = updataFile(file, targetParent, url)
            //返回下载成功
            emit(DownloadStatus.onSuccess(newFile))

        }.onCompletion {
            bufferedInputStream?.close()
            outputStream?.close()
            inputStream?.close()
        }.catch { error ->
            LogUtils.e("error:${error}")

        }

    }


    fun updataFile(oldFile: File, targetPath: String, downloadUrl: String): File {

        val fileType = downloadUrl.substring(downloadUrl.lastIndexOf("."))
        LogUtils.e("fileType:${fileType}")
        var fileName = YgxUtilsKt.md5String(downloadUrl);
        fileName = "${fileName}${fileType}"

        //修改文件名为正式的
        val newPathFile = File(targetPath, fileName)
        oldFile.renameTo(newPathFile)

        return if (newPathFile.exists()) {
            newPathFile
        } else {
            oldFile
        }

    }

    //检查要下载的文件是否已经存在本地了
    private fun checkDownloadFile(fileUrl: String, outputFile: String): File? {

        val fileType = fileUrl.substring(fileUrl.lastIndexOf("."))

        var fileName = YgxUtilsKt.md5String(fileUrl);

        fileName = "${fileName}${fileType}"
        val localFile = File(outputFile, fileName)

        return if (localFile.exists()) {
            localFile
        } else {
            null
        }
    }

    //临时文件
    private fun getFileTmpName(fileUrl: String): String {
        return "${YgxUtilsKt.md5String(fileUrl)}.tmp"
    }
}